﻿fs.calc = function (calc) {
    fs_PartRefresh = true;
    calc.allRow = [];
    calc.init = function () {

        //        $("table.commontable tr[row]").each(function () {
        //            calc.allRow.push({ rowid: $(this).attr('row'), control: this });
        //        });
        $("table.commontable td[calc=true]").each(function () {
            var self = $(this);
            calc.equs.push(self, self.attr("calctype"));
        })
    }

    calc.refreshCurrentRow = function (obj) {
        obj.parents("tr:first").find("td[calc=true]").trigger("calculate");
    }

    calc.setCalc = function (obj) {
        var oldValue = new Date();

        if (typeof obj != 'undefined' && fs_PartRefresh) {

            var scope = obj.parents("tr:first").attr("scope");
            if (scope) {
                $("tr[scope=" + scope + "]").find("td[calctype=PREV]").trigger("calculate");
                $("tr[scope=" + scope + "]").find("td[calctype=UNTIL]").trigger("calculate");
                $("tr[scope=" + scope + "]").find("td[calctype=NEXT]").trigger("calculate");
                $("tr[scope=" + scope + "]").find("td[calctype=CM]").trigger("calculate");

                //fs.util.log("scope Calc " + (oldValue.getSeconds() - (new Date()).getSeconds()) + ":" + (oldValue.getMilliseconds() - (new Date()).getMilliseconds()));
                fs.calc.control();
                return;
            }

            obj.parents("tr:first").find("td[calc=true]").trigger("calculate");
            //fs.util.log("CurrentRow  " + (oldValue.getSeconds() - (new Date()).getSeconds()) + ":" + (oldValue.getMilliseconds() - (new Date()).getMilliseconds()));

            //  fs.util.log("PREV  " + (oldValue.getSeconds() - (new Date()).getSeconds()) + ":" + (oldValue.getMilliseconds() - (new Date()).getMilliseconds()));

            calc.equs.refresh("UNTIL");
            //  fs.util.log("UNTIL  " + (oldValue.getSeconds() - (new Date()).getSeconds()) + ":" + (oldValue.getMilliseconds() - (new Date()).getMilliseconds()));

            calc.equs.refresh("PREV");

            calc.equs.refresh("NEXT");
            // fs.util.log("NEXT  " + (oldValue.getSeconds() - (new Date()).getSeconds()) + ":" + (oldValue.getMilliseconds() - (new Date()).getMilliseconds()));

            calc.equs.refresh("CM");
            // fs.util.log("CM  " + (oldValue.getSeconds() - (new Date()).getSeconds()) + ":" + (oldValue.getMilliseconds() - (new Date()).getMilliseconds()));

            //   calc.equs.refresh("YTDM");
        } else {
            $("table.commontable td[calc=true]").trigger("calculate");
            //fs.util.log("All Calc");
        }

        fs.calc.control();
        //fs.util.log((oldValue.getSeconds() - (new Date()).getSeconds()) + ":" + (oldValue.getMilliseconds() - (new Date()).getMilliseconds()));
    }

    calc.equation = [{ YTDM: '({0})+({1})' }, { Movement: '({0})-({1})'}];

    calc.getEqu = function (t) {
        for (var i = 0; i < fs.calc.equation.length; i++) {
            var res = fs.util.ref(fs.calc.equation[i], t, null);
            if (res) return res;
        }
    }
    calc.getTRValue = function (tr) {
        var trInput = tr.find("input[type=text]");
        var v = 0;
        if (trInput.length > 0)
            v = trInput.val();
        else
            v = tr.text();

        return v.toFix();
    }
    calc.getArgValue = function (rowid, t) {
        var warpControl = $("table.commontable tr[row=" + rowid + "]").find("td[type=" + t + "]");
        return fs.util.getValue(warpControl);
    }

    //no use
    calc.makCalcInstance = function (self) {
        return {
            rowid: "",
            self: self,
            type: self.attr('type'),
            calctype: self.attr('calctype'),
            equ: self.attr("equ"),
            source: self.attr('from').split(',')
        };
    }

    calc.calculate = function (e, t) {
        var self = $(this); //, rowid, equ, source = self.attr('from').split(','), t = self.attr('type');

        var args = {
            rowid: "",
            self: self,
            type: self.attr('type'),
            calctype: self.attr('calctype'),
            ma: self.attr("ma"), // manual and auto 
            equ: self.attr("equ"),
            source: self.attr('from').split(',')
        }
        if (args.ma == "manual") return;

        var equ = calc.equs.get(args);

        fs.util.setValue(self, fs.util.eval(equ));

    }

    calc.control = function () {
        var allControls = $("div[type=Control]");
        $(allControls).each(function () {
            var allField = $(this).find("span");
            allField.each(function () {
                var self = $(this);
                if (!self.attr("receive")) {
                    var args = { rowid: self.attr("from"), type: self.attr("field") };
                    self.text(fs.calc.getArgValue(args.rowid, args.type));
                }
            });
            var self = $(this);
            var displayArea = typeof self.attr("display") != 'undefined' ? self.attr("display") : "div.fs-control-display";

            var displayDom = self.parents("tr[control]").find(displayArea);
            var equ = self.text();
            var equresult = fs.util.eval(equ);
            //            equresult = equresult ? equresult.toFixed(2) : 0.00;
            //            displayDom.text(equresult);

            if (document.controlCalcEqual & equresult != "0")
                document.controlCalcEqual = false;

            fs.util.setValue(displayDom, equresult, 2);
        });

    }
    calc.CommonHandler = function (args) {
        args.equ = fs.calc.getEqu(args.type);
        args.rowid = args.self.parents("tr[row]").attr('row');

        for (var i = 0; i < args.source.length; i++) {
            args.equ = args.equ.replace('{' + i + '}', fs.calc.getArgValue(args.rowid, args.source[i]));
        }

        return args.equ;
    };
    //not use
    calc.filterDom = function (args, untilDom) {

        var from = args.self.attr("from"), equ = "", neq = args.self.attr("neq");

        $(untilDom).each(function () {
            var trNode = $(this).find("td[type=" + from + "]");
            if (neq) {
                var neqs = neq.split(",");

                $(neqs).each(function () {
                    trNode = trNode.find("td[" + this + "]"); ;
                })
            }

            var val = fs.util.getValue(trNode);
            equ += (val ? val : 0) + "+";
        });
        return equ.substring(0, equ.length - 1);
    }
    calc.equs = {
        handlers: [{
            "type": "YTDM",
            controls: [],
            handler: calc.CommonHandler
        }, {
            "type": "Movement",
            controls: [],
            handler: calc.CommonHandler
        }, {
            "type": "CM",
            controls: [],
            handler: function (args) {

                for (var i = 0; i < args.source.length; i++) {
                    //ID&Type
                    var fieldSource = args.source[i].split("&");
                    args.equ = args.equ.replace('{' + i + '}', "(" + fs.calc.getArgValue(fieldSource[0], fieldSource[1]) + ")");
                }

                return args.equ;
            }
        }, {
            "type": "NEXT",
            controls: [],
            handler: function (args) {

                var untilDom = args.self.nextAll();
                //如果有公式，就根据公式来过滤
                if (args.equ) {
                    untilDom = parentTR.nextUntil(args.equ);
                }
                var from = args.self.attr("from"), equ = "";

                $(untilDom).each(function () {

                    var vlidate = from ? $(this).attr("type") == from : true;
                    if (vlidate) {
                        var trNode = $(this);
                        var val = fs.util.getValue(trNode);
                        equ += (val ? val : 0) + "+";
                    }
                });
                return equ.substring(0, equ.length - 1);
            }
        }, {
            "type": "UNTIL",
            controls: [],
            handler: function (args) {
                var parentTR = args.self.parent();
                var untilDom = null;
                //如果有公式，就根据公式来过滤
                if (args.equ) {
                    untilDom = parentTR.nextUntil(args.equ);
                } else {//没有就查所有上面的
                    untilDom = parentTR.nextAll("tr[row]");
                }
                var from = args.self.attr("from"), equ = "";

                $(untilDom).each(function () {
                    var trNode = $(this).find("td[type=" + from + "]");
                    var val = fs.util.getValue(trNode);
                    equ += (val ? val : 0) + "+";
                });
                return equ.substring(0, equ.length - 1);
            }
        }, {
            "type": "PREV",
            controls: [],
            handler: function (args) {
                var parentTR = args.self.parent();
                var untilDom = null;
                //如果有公式，就根据公式来过滤
                if (args.equ) {
                    untilDom = parentTR.prevUntil(args.equ);
                } else {//没有就查所有上面的
                    untilDom = parentTR.prevAll("tr[row]");
                }
                var from = args.self.attr("from"), equ = "";

                $(untilDom).each(function () {
                    var trNode = $(this).find("td[type=" + from + "]");
                    var val = fs.util.getValue(trNode);
                    equ += (val ? val : 0) + "+";
                });
                return equ.substring(0, equ.length - 1);
            }
        }],
        push: function (control, type) {
            var handler = fs.util.search(this.handlers, "type", type);
            if (fs.util.getValue(control).toString().trim() == '')
                fs.util.setValue(control, 0.00);

            control.fs_index = control.attr('fs_index') ? parseInt(control.attr('fs_index')) : 0;
            if (handler.length > 0)
                handler[0].controls.push(control);
        },
        refresh: function (type) {
            if (!type) {
                for (var i = 0; i < this.handlers; i++) {
                    $(this.handlers[i].controls.sort(by('fs_index'))).trigger("calculate");
                    // calc.refreshCurrentRow(this.handlers[i].controls);
                }

                //fs.util.log("Rerefsh All");
                return;
            }
            var handler = fs.util.search(this.handlers, "type", type);
            $(handler[0].controls.sort(by('fs_index'))).each(function () {
                //calc.refreshCurrentRow(this);
                var self = $(this);
                self.trigger("calculate");
                setTimeout(function () {
                    self.parent().find("td[type=YTDM]").trigger('calculate');
                    self.parent().find("td[type=Movement]").trigger('calculate');
                }, 100);
            })
            //fs.util.log(type + " Rerefsh");
        },
        get: function (args) {
            var fun = fs.util.search(this.handlers, "type", args.calctype);
            return fun[0].handler(args);
        }
    }

    return calc;
} (fs.calc || {});